package com.xcity.game.combat;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;

import com.alibaba.fastjson.annotation.JSONField;
import com.xcity.game.combat.buff.CombatBuff;
import com.xcity.game.combat.listener.ActionListener;
import com.xcity.game.combat.skill.CombatSkill;
import com.xcity.game.combat.unit.CombatUnit;
import com.xcity.game.skill.template.SkillTemplate;

/**
 * 一次战斗行动
 * @author yang.li
 *
 */
public class Action {

	protected Round ref;
//	protected int order;
	protected int index;
	@JSONField(serialize = false)
	public CombatUnit unit; // 执行本次行动的战斗单位
	protected int skillId; // 本次行动释放的技能
	protected boolean useSkill;
	@JSONField(serialize = false)
	public CombatTeam target;
	protected List<ActionEffect> effects; // 本次行动产生的效果
	protected List<CombatBuff> buffs; // 本次行动产生的buff
	
	public static final int DEFAULT_ACTION_TIME = 3000; // 一次行动默认时长1秒
	protected static final Logger LOG = CombatService.LOG;
	
	public Action(/*Round ref, */CombatUnit unit/*, int order*/) {
		this(/*ref, */unit,/* order,*/ false);
	}
	
	public Action(/*Round ref, */CombatUnit unit,/* int order,*/ boolean useSkill) {
//		this.ref = ref;
		this.unit = unit;
//		this.order = order;
		this.useSkill = useSkill;
//		this.effects = new ArrayList<ActionEffect>();
	}
	
	public ActionEffect addTarget(CombatUnit target) {
		if (effects == null)
			effects = new ArrayList<ActionEffect>(5);
		CombatUnit u = unit.preTarget(this);
		if (u != null) {
			target = u;
		}
		ActionEffect effect = new ActionEffect(this, target);
		effects.add(effect);
		return effect;
	}
	
	public void addBuff(CombatBuff buff) {
		boolean succ = buff.getOwner().addBuff(buff);
		if (succ && buff.getTemplate() != null/*某些buff没有配置，仅在服务器计算，不通知客户端*/) {
			if (buffs == null)
				buffs = new ArrayList<CombatBuff>(5);
			buffs.add(buff.clone()); // buff.clone拷贝一个副本，避免本回合失效的buff在客户端显示不出
		}
	}
	
	public void execute(ActionListener listener) {
		// IQ->攻击、防御
		// EQ->法攻、法防、攻速、暴击
		// AQ->免暴、血量
		// 防御力减伤=防御力*0.35
		// 法防减伤=法防*0.35
		// 暴击伤害=普攻伤害*1.35
		// 免暴抵消暴击率=免暴*0.0005
		// 暴击率=暴击*0.000521
//		1：技能、攻击、暴击等属性修正
//		2：命中计算（攻击是否miss，目标是否免疫）
//		3：若命中，则计算伤害
//		4：反击、治疗计算
		if (listener != null) {
			listener.preAction(this);
		}
		unit.preAction(this);
		
		CombatSkill skill = null;
		if (useSkill) {
			skill = unit.findSkillByType(SkillTemplate.TYPE_ACTIVE);
		}
		if (skill != null) {
			skillId = skill.getId();
			skill.calcDamage(this);
		} else {
			calc();
		}
		
		unit.afterAction(this);
		if (listener != null) {
			listener.afterAction(this);
		}
	}
	
	private void calc() {
		CombatUnit target = this.target.getDefenseUnit(unit.getIndex());
		ActionEffect effect = addTarget(target);
		CombatUtils.calcAttack(effect);
//		float critRate = unit.getCrit() * 0.000521f;
//		CombatUnit target = this.target.getDefenseUnit();
//		if (target != null) {
//			ActionEffect eff = addTarget(target);
//			target = eff.unit; // 修正目标
//			float avoidCritRate = target.getAvoidCrit() * 0.0005f;
//			float _critRate = critRate - avoidCritRate;
//			int damage = 0;
//			if (_critRate > 0f && Math.random() < _critRate) {
//				// 产生暴击
//				eff.result = ActionEffect.RESULT_CRIT;
//			} else {
//				// 普攻
//				eff.result = ActionEffect.RESULT_HIT;
//			}
//			if (eff.isHit()) {
//				damage = (int) (eff.result == ActionEffect.RESULT_CRIT
//						? unit.getAttackPower() * 1.35f - target.getDefense() * 0.35f
//								: unit.getAttackPower() - target.getDefense() * 0.35f);
//				damage = CombatUtils.correctDamage(damage);
//				eff.effect(CombatAttribute.Type.HP, -damage);
//			}
//		}
//			LOG.info("[COMBAT ACTION]SOURCE[{}]TARGET[{}]HPDELTA[{}]HP[{}]", unit.getId(), eff.unit.getId(), eff.hpDelta, eff.unit.getHp());
	}
	
	public synchronized void rollback(Combat combat) {
		for (int i = effects.size() - 1; i >= 0; i--) {
			effects.get(i).rollback();
		}
//		if (order != -1) {
//			combat.order = order;
//		}
	}
	
	public Round ref() {
		return ref;
	}
	
	//---getters---
	public int getIndex() {
		return index;
	}
	
	public long getUnitId() {
		return unit.getId();
	}
	
	public int getSkillId() {
		return skillId;
	}

	public List<ActionEffect> getEffects() {
		return effects != null ? effects : Collections.emptyList();
	}

	public List<CombatBuff> getBuffs() {
		return buffs != null ? buffs : Collections.emptyList();
	}
	//---getters---
}
